import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { Common } from '../common/common';
import { InjectRepository } from '@nestjs/typeorm';
import { VerificationCodes } from '../../module/VerificationCodes';
import { Repository } from 'typeorm';
import { VerifyCodeInterface } from './interface/verifyCode.interface';
import { CommonUtil } from '../../@nt/utils/commonUtil';
import * as moment from 'moment';
import { CrontabService } from '../crontab/crontab.service';
import { Mailer } from '../../@nt/utils/mailer';
import Redis from 'ioredis';
import { RedisService } from '@liaoliaots/nestjs-redis';
import { RedisConfig } from '../../@nt/config';

@Injectable()
export class VerifyCodeService extends Common implements OnModuleInit {
  private readonly logger = new Logger(VerifyCodeService.name);
  private readonly redis: Redis | null;

  constructor(
    @InjectRepository(VerificationCodes)
    private readonly verificationCodesRepository: Repository<VerificationCodes>,
    private readonly crontabService: CrontabService,
    private readonly redisService: RedisService,
  ) {
    super();
    this.redis = this.redisService.getOrThrow();
  }

  onModuleInit() {
    this.crontabService.defineJob(
      'verifycode.expire.job',
      this.expireCodeJob.bind(this),
    );
  }

  /**
   * 处理过期验证码
   * @param job
   * @param done
   */
  async expireCodeJob(job: any, done: any): Promise<void> {
    this.logger.log(JSON.stringify(job));
    const data: any = job;
    const where: any = {
      id: data.id,
    };
    await this.verificationCodesRepository.update(where, { status: 2 });
    done();
  }

  /**
   * 发送验证码
   * @param body
   */
  async create(body: VerifyCodeInterface): Promise<any> {
    const where: any = {
      email: body.email,
      status: 0,
    };
    const verificationCode = await this.verificationCodesRepository.findOne({
      where,
    });
    if (!verificationCode) {
      const expiredAt = moment().add(10, 'minutes').unix();
      const code = CommonUtil.randomDigitNumber(6);
      const data: any = {
        email: body.email,
        code,
        expiredAt,
      };
      const mailBody: any = {
        to: body.email,
        subject: '验证码',
        text: `您的验证码为：${code}，有效期为10分钟，请勿泄露给他人。`,
      };
      const mailResult: boolean = await Mailer.emailTo(mailBody);
      console.log('发送邮件结果', mailResult);
      if (!mailResult) {
        return this.returnJson(2001, null, '验证码邮件发送失败，请重试');
      }
      const result: VerificationCodes =
        await this.verificationCodesRepository.save(data);
      if (result) {
        this.redis.setex(
          `${RedisConfig.verifyCode}${result.email}`,
          600,
          JSON.stringify(result),
        );
        this.crontabService.scheduleJob(
          'verifycode.expire.job',
          moment.unix(expiredAt).toISOString(),
          result,
        );
      }
    } else {
      const mailBody: any = {
        to: body.email,
        subject: '验证码',
        text: `您的验证码为：${verificationCode.code}，有效期为10分钟，请勿泄露给他人。`,
      };
      await Mailer.emailTo(mailBody);
    }
    return this.returnJson(0, true, '验证码邮件发送成功');
  }
}
